#!/usr/bin/env python3
"""
DVHealth 系统性能测试 - Locust 测试脚本

用于测试健康管理系统的性能表现，包括用户认证、健康数据管理、API响应等。
"""

import random
from datetime import datetime, timedelta
from locust import HttpUser, task, between
import json


class DVHealthUser(HttpUser):
    """DVHealth系统用户性能测试类"""
    
    # 请求间隔时间（秒）
    wait_time = between(1, 5)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.token = None
        self.user_id = None
        self.headers = {}
    
    def on_start(self):
        """用户启动时执行 - 登录获取token"""
        self.login()
    
    def login(self):
        """用户登录 - 使用固定验证码进行性能测试"""
        # 生成随机手机号（模拟不同用户）
        # phone_prefix = "1380000"
        # phone_suffix = str(random.randint(1000, 9999)).zfill(4)
        # phone_number = f"{phone_prefix}{phone_suffix}"
        phone_number = "18835625015"
        
        # 先获取验证码
        with self.client.post("/api/users/generate-code/", 
                             json={"phone_number": phone_number},
                             catch_response=True) as response:
            if response.status_code == 200:
                # 验证码获取成功，使用固定验证码 "123456" 进行登录
                login_data = {
                    "phone_number": phone_number,
                    "input_verification_code": "123456"  # 固定验证码用于性能测试
                }
                
                # 执行登录
                with self.client.post("/api/users/login/", 
                                     json=login_data,
                                     catch_response=True) as login_response:
                    if login_response.status_code == 200:
                        result = login_response.json()
                        self.token = result.get("access_token")
                        self.user_id = result.get("user", {}).get("id")
                        self.headers = {
                            "Authorization": f"Bearer {self.token}",
                            "Content-Type": "application/json"
                        }
                        login_response.success()
                    else:
                        login_response.failure(f"登录失败: {login_response.status_code}")
            else:
                response.failure(f"获取验证码失败: {response.status_code}")
    
    @task(3)
    def test_user_profile(self):
        """测试获取用户个人资料"""
        self.client.get("/api/users/profile/", headers=self.headers)
    
    # @task(5)
    # def test_health_dashboard(self):
    #     """测试健康数据面板"""
    #     # 测试用户健康数据统计
    #     self.client.get("/api/health/user-health-stats/", headers=self.headers)
    
    # @task(4)
    # def test_yesterday_analysis(self):
    #     """测试昨日健康数据分析"""
        # self.client.get("/api/health/user-yesterday-analysis/", headers=self.headers)
    
    @task(4)
    def test_body_records(self):
        """测试身体指标记录"""
        self.client.get("/api/health/body-records/", headers=self.headers)
    
    @task(3)
    def test_eating_records(self):
        """测试饮食记录"""
        self.client.get("/api/health/eating-records/", headers=self.headers)
    
    @task(3)
    def test_sleep_records(self):
        """测试睡眠记录"""
        self.client.get("/api/health/my-sleep-records/", headers=self.headers)
    
    @task(3)
    def test_sports_records(self):
        """测试运动记录"""
        self.client.get("/api/health/my-sports-records/", headers=self.headers)
    
    @task(2)
    def test_create_body_record(self):
        """测试创建身体指标记录"""
        body_data = {
            "weight": round(random.uniform(50, 100), 1),
            "height": round(random.uniform(150, 190), 1),
            "blood_pressure_systolic": random.randint(100, 140),
            "blood_pressure_diastolic": random.randint(60, 90),
            "heart_rate": random.randint(60, 100),
            "blood_sugar": round(random.uniform(4.0, 8.0), 1),
            "record_date": (datetime.now() - timedelta(days=random.randint(0, 7))).strftime("%Y-%m-%d")
        }
        self.client.post("/api/health/body-records/", 
                        json=body_data, 
                        headers=self.headers)
    
    @task(1)
    def test_create_eating_record(self):
        """测试创建饮食记录"""
        eating_data = {
            "food_name": f"测试食物{random.randint(1, 100)}",
            "calories": random.randint(100, 500),
            "protein": round(random.uniform(5, 30), 1),
            "carbohydrates": round(random.uniform(10, 60), 1),
            "fat": round(random.uniform(5, 25), 1),
            "eating_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        self.client.post("/api/health/eating-records/", 
                        json=eating_data, 
                        headers=self.headers)
    
    @task(1)
    def test_create_sleep_record(self):
        """测试创建睡眠记录"""
        sleep_data = {
            "sleep_duration": round(random.uniform(5, 9), 1),
            "sleep_quality": random.choice(["优", "良", "中", "差"]),
            "bedtime": (datetime.now() - timedelta(hours=10)).strftime("%Y-%m-%d %H:%M:%S"),
            "wakeup_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        self.client.post("/api/health/sleep-records/", 
                        json=sleep_data, 
                        headers=self.headers)
    
    @task(1)
    def test_create_sports_record(self):
        """测试创建运动记录"""
        sports_data = {
            "sport_type": random.choice(["跑步", "游泳", "健身", "骑行"]),
            "duration": random.randint(30, 120),
            "distance": round(random.uniform(1, 10), 1),
            "calories_burned": random.randint(200, 800),
            "intensity": random.choice(["低", "中", "高"]),
            "sport_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        }
        self.client.post("/api/health/sports-records/", 
                        json=sports_data, 
                        headers=self.headers)
    


class DVHealthAdminUser(HttpUser):
    """管理员用户性能测试类"""
    
    wait_time = between(2, 8)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.token = None
        self.headers = {}
    
    def on_start(self):
        """管理员登录"""
        self.admin_login()
    
    def admin_login(self):
        """管理员登录"""
        login_data = {
            "username": "admin",
            "password": "admin123456"
        }
        
        with self.client.post("/api/users/admin/login/", 
                             json=login_data,
                             catch_response=True) as response:
            if response.status_code == 200:
                result = response.json()
                print(f"管理员登录响应内容: {result}")
                self.token = result.get("access_token")
                self.headers = {
                    "Authorization": f"Bearer {self.token}",
                    "Content-Type": "application/json"
                }
                response.success()
            else:
                response.failure(f"管理员登录失败: {response.status_code}")
    
    @task(4)
    def test_admin_dashboard(self):
        """测试管理员面板"""
        self.client.get("/api/users/users", headers=self.headers)
    
    @task(3)
    def test_user_management(self):
        """测试用户管理"""
        # 获取用户列表
        self.client.get("/api/users/users/?page=1", headers=self.headers)
    


class AnonymousUser(HttpUser):
    """匿名用户性能测试类"""
    
    wait_time = between(3, 10)
    
    @task(5)
    def test_public_apis(self):
        """测试公开API（如健康资讯等）"""
        self.client.get("/api/health/health-news/", name="获取健康资讯")
    
    @task(3)
    def test_api_docs(self):
        """测试API文档访问"""
        self.client.get("/api/schema/swagger-ui/", name="Swagger文档")
        self.client.get("/api/schema/redoc/", name="ReDoc文档")


class HighLoadUser(HttpUser):
    """高负载用户测试类 - 模拟高并发场景"""
    
    wait_time = between(0.1, 1)
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.token = None
        self.headers = {}
    
    def on_start(self):
        """快速登录"""
        # 生成随机手机号
        phone_prefix = "1380000"
        phone_suffix = str(random.randint(2000, 2999)).zfill(4)
        phone_number = f"{phone_prefix}{phone_suffix}"
        
        # 先获取验证码
        with self.client.post("/api/users/generate-code/", 
                             json={"phone_number": phone_number},
                             catch_response=True) as response:
            if response.status_code == 200:
                # 使用固定验证码登录
                login_data = {
                    "phone_number": phone_number,
                    "input_verification_code": "123456"
                }
                
                with self.client.post("/api/users/login/", 
                                     json=login_data,
                                     catch_response=True) as login_response:
                    if login_response.status_code == 200:
                        result = login_response.json()
                        self.token = result.get("access_token")
                        self.headers = {
                            "Authorization": f"Bearer {self.token}",
                            "Content-Type": "application/json"
                        }
    
    # @task(10)
    # def test_rapid_health_queries(self):
    #     """快速健康数据查询"""
    #     self.client.get("/api/health/user-health-stats/", headers=self.headers)
    
    @task(5)
    def test_rapid_dashboard_access(self):
        """快速仪表板访问"""
        self.client.get("/api/health/body-records/", headers=self.headers)


# 性能测试场景配置
class PerformanceTestConfig:
    """性能测试配置类"""
    
    # 测试场景配置
    SCENARIOS = {
        "normal_load": {
            "user_classes": [DVHealthUser, AnonymousUser],
            "weights": [70, 30],  # 70%普通用户，30%匿名用户
            "spawn_rate": 10,  # 每秒生成用户数
            "users": 100  # 总用户数
        },
        "admin_load": {
            "user_classes": [DVHealthAdminUser],
            "weights": [100],
            "spawn_rate": 5,
            "users": 20
        },
        "high_load": {
            "user_classes": [HighLoadUser],
            "weights": [100],
            "spawn_rate": 50,
            "users": 500
        },
        "mixed_load": {
            "user_classes": [DVHealthUser, AnonymousUser, DVHealthAdminUser],
            "weights": [60, 30, 10],
            "spawn_rate": 20,
            "users": 200
        }
    }
    
    # 性能指标阈值
    PERFORMANCE_THRESHOLDS = {
        "response_time": {
            "p95": 2000,  # 95%的请求应在2秒内完成
            "p99": 5000   # 99%的请求应在5秒内完成
        },
        "error_rate": {
            "max": 0.01  # 错误率不超过1%
        },
        "throughput": {
            "min": 50  # 最小吞吐量50请求/秒
        }
    }


if __name__ == "__main__":
    """
    本地运行测试的脚本
    使用命令: python locustfile.py
    """
    import os
    import sys
    
    print("DVHealth 性能测试脚本")
    print("=" * 50)
    print("测试场景:")
    for scenario_name, config in PerformanceTestConfig.SCENARIOS.items():
        print(f"  - {scenario_name}: {config['users']} 用户, {config['spawn_rate']} 用户/秒")
    print()
    print("性能指标阈值:")
    print(f"  响应时间: P95 < {PerformanceTestConfig.PERFORMANCE_THRESHOLDS['response_time']['p95']}ms")
    print(f"  响应时间: P99 < {PerformanceTestConfig.PERFORMANCE_THRESHOLDS['response_time']['p99']}ms")
    print(f"  错误率: < {PerformanceTestConfig.PERFORMANCE_THRESHOLDS['error_rate']['max'] * 100}%")
    print(f"  吞吐量: > {PerformanceTestConfig.PERFORMANCE_THRESHOLDS['throughput']['min']} 请求/秒")
    print()
    print("运行命令:")
    print("  locust -f locustfile.py --host=http://localhost:8000")
    print("  locust -f locustfile.py --host=http://your-server-ip:8000")
    print()
    print("Web界面: http://localhost:8089")